package format

import (
	"fmt"
	"strings"
	"sync"

	"gitee.com/sansaniot/ssiot-core/facade/runtime"
	"gitee.com/sansaniot/ssiot-core/logger"
	"gorm.io/gorm"

	"ssdevice/common/constant"
	"ssdevice/common/enums"
	"ssdevice/common/utils"
	"ssdevice/internal/device/models"
)

type HasCreateTable struct {
	TableList  sync.Map
	TableCount int
}

// 生成历史入库表并返回入库信息
// TODO repository gorm实现不同数据库类型
func GenHisTableData(cacheData map[string]interface{}, hasCreateTable *HasCreateTable) map[string][]map[string]interface{} {
	sn := cacheData["sn"].(string)
	updateTime, _ := utils.FormatStrTime(cacheData["updateTime"].(string))
	dataMap := cacheData["data"].(map[string]interface{})
	// 用model类的话,value不能入库
	hisDataMap := make(map[string][]map[string]interface{})
	var tableName string
	var valueType string
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return hisDataMap
	}
	for k, v := range dataMap {
		typeOf := fmt.Sprintf("%T", v)
		// 注意if顺序
		if strings.Contains(typeOf, "[]") {
			typeOf = "array"
			valueType = "jsonb"
		} else if strings.Contains(typeOf, "map[string]interface") {
			typeOf = "object"
			valueType = "jsonb"
		} else if strings.Contains(typeOf, "string") {
			typeOf = "string"
			valueType = "varchar(255)"
		} else if strings.Contains(typeOf, "nil") {
			typeOf = "nil"
			continue
		} else if strings.Contains(typeOf, "bool") {
			typeOf = "boolean"
			valueType = "bool"
		} else {
			// 数字统一处理
			typeOf = "number"
			valueType = "float8"
		}
		tableName = strings.ToLower("sys_z_" + k + "_" + typeOf)
		//判断表是否存在, 并初始表结构
		exist := db.Migrator().HasTable(tableName)
		if !exist {
			if err := db.Exec(`
		CREATE TABLE "` + tableName + `" (
			"id" SERIAL8 NOT NULL,
			"dev_sn" varchar(255) NOT NULL,
			"value" ` + valueType + `,
			"update_time" timestamptz(6) NOT NULL
		);
		CREATE INDEX "` + tableName + "_updateTime" + `" ON "` + tableName + `" USING btree (
		  "update_time" "pg_catalog"."timestamptz_ops" ASC NULLS LAST
		);`).Error; err != nil {
				logger.Error(err)
				continue
			}
		} else {
			hasCreateTable.TableList.Store(tableName, true)
			hasCreateTable.TableCount++
		}
		// 准备入库
		if _, ok := hisDataMap[tableName]; !ok {
			hisDataMap[tableName] = make([]map[string]interface{}, 0)
		}
		hisDataMap[tableName] = append(hisDataMap[tableName], map[string]interface{}{
			"dev_sn":      sn,
			"value":       v,
			"update_time": updateTime,
		})
	}
	return hisDataMap
}

func GetFromTo(devSn string, jsonData map[string]interface{}, needModel bool) (devType, to string) {
	if from, ok := jsonData["from"]; ok && from != nil && len(from.(string)) > 0 && from.(string) != devSn {
		to = from.(string)
	}
	if needModel {
		modelValue := utils.GetStringValueFiled(utils.GetMapValueFiled(jsonData, "data"), "model")
		if len(modelValue) == 0 {
			// 空则为device
			devType = enums.DevTypeOfDevice
		} else {
			db := runtime.Runtime.GetDbByKey("db")
			if db == nil {
				return
			}
			sysDevProduct := &models.SysDevProduct{}
			sysDevProduct.Orm = db
			modelMapper := sysDevProduct.GetModelMapper()
			var exist bool
			// 取配置的值
			devType, exist = modelMapper[modelValue]
			if !exist || len(devType) == 0 {
				// 没配置，默认为device
				devType = enums.DevTypeOfDevice
			}
		}
	}
	return
}

// 获取goto
func GetLoginRedirectAddr(db *gorm.DB, dev models.SysDev) (goTo string) {
	if len(dev.DeptId) == 0 || dev.DeptId == constant.DefaultGroupId || dev.DeptId == constant.AnonymousGroupId {
		// 设备无分组/匿名分组  取admin的goto配置
		adminUser := EasyUser{}
		sql := `
SELECT 
	u.ID,
	u.username,
	u.is_agency,
	u."goto"
FROM
	sys_user u
WHERE
	u.ID = '1' 
`
		if err := db.Raw(sql).Scan(&adminUser).Error; err != nil {
			logger.Error(err)
			return
		}
		goTo = adminUser.Goto
	} else {
		// 取分组对应的机构用户的goto配置
		userList := make([]EasyUser, 0)
		sql := `
SELECT DISTINCT
	u.ID,
	u.username,
	u.is_agency,
	u."goto",
	ud.dept_id 
FROM
	sys_user u
	LEFT JOIN sys_user_dept_r ud
	LEFT JOIN sys_dept d ON ud.dept_id = d.ID ON u.ID = ud.user_id 
WHERE
	( u.is_agency = '1' OR u.ID = '1' ) 
	AND ud.dept_id = ?
`
		if err := db.Raw(sql, dev.DeptId).Scan(&userList).Error; err != nil {
			logger.Error(err)
			return
		}
		if len(userList) == 1 {
			goTo = userList[0].Goto
		} else if len(userList) > 1 {
			// admin、机构用户都有的情况 取机构用户的配置
			for _, v := range userList {
				if v.UserId == "1" {
					continue
				}
				// 优先取机构用户中 有配置的
				if len(v.Goto) > 0 {
					goTo = v.Goto
				}
			}
		}
	}
	return
}

type EasyUser struct {
	UserId   string `json:"id"`
	Username string `json:"username"`
	IsAgency string `json:"is_agency"`
	Goto     string `json:"goto"`
	DeptId   string `json:"dept_id"`
}
